/**********************************
 * Author: Mike Truong
 * Date: 7/26/2014
 * Description: Test dominion.c w/ random # player and random kingdom cards
 * ********************************/


#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <time.h>
#include "rngs.h"

void printName(int cardNumber);

void printHand(struct gameState state, int player);

void printDeck(struct gameState state, int player);

void printDiscard(struct gameState state, int player);

void printBuyCard(struct gameState state, int player, int card, int test);


int main(){

	//random time seed
	srand(time(NULL));

	int i = 0;
	int j = 0;
	int s;
	int r;
	int player, card, coins, choice1, choice2, choice3, cardPos;
	//Used to hold random numbers, initially for seeding into initializeGame
	int randNum = (rand() % 1234567);
	//generate a random number of players	
	int playerCount = (rand() % 3) + 2;
	int round = 0;
	struct gameState G;
	int k[10];
	int kP[20] = { adventurer, council_room, feast, gardens, mine, remodel, smithy, village, baron, great_hall, minion, steward, tribute, ambassador, cutpurse, embargo, outpost, salvager, sea_hag, treasure_map };
	int possible[17];

	//Pick 10 kingdom cards at random
	while( i < 10) {
		randNum = (rand() % 20);
		if (kP[randNum] !=0) {
			k[i] = kP[randNum];
			kP[randNum] = 0;
			i++;
		}
	}

	r = initializeGame(playerCount, k, randNum, &G);
	assert(r == 0);

	//Create an array of all possible choices
	for( int z = 0; z < 7; z++) {
		possible[z] = z;
	}
	for( int z = 0; z < 10; z++)
	{
		possible[(z+7)] = k[z];
	}

	printf("\n*******Game Start*******\n");

	printf("Player count = %d\n", playerCount);
	printf("Kingdom cards picked:\n");

	for (int z = 0; z < 10; z++){
		printf("%d. ", (z + 1));
		printName(k[z]);
		printf(".\n");
	}

	//while the game is not over run this loop
	while (!isGameOver(&G)) {
		player = whoseTurn(&G);
		choice1 = choice2 = choice3 = -1;
		//Print round number
		if ((j % playerCount) == 0){
			round++;
			printf("\n-----Round %d-----\n", round);
		}
		printf("\n-----Player %d's Turn-----\n", (player + 1));
		printHand(G, player);
		printDeck(G, player);
		printDiscard(G, player);

		randNum = (rand() % 100);
		if (randNum > 20){
			printf("ACTION PHASE.\n");
			printf("BEFORE ACTION - Player %d's action count = %d.\n", (player + 1), G.numActions);
			printf("BEFORE ACTION - Player %d coins = %d.\n", (player + 1), G.coins);
			if (randNum > 55){
				//do this for every card in the player's hand
				for (i = 0; i < G.handCount[player]; i++){
					if ((G.hand[player][i] >= adventurer) && (G.hand[player][i] <= treasure_map)){
						card = G.hand[player][i];
						cardPos = i;
						printf("Player %d plays ", (player + 1));
						printName(card);
						printf(".\n");
						switch (card){
						case feast:
							//Choose a random card besides province, gold, or adventurer
							randNum = floor(rand() % 17);
							while ((randNum != 7) && (randNum != 3) && (randNum != 6)){
								randNum = floor(rand() % 17);
							}
							choice1 = possible[randNum];
							break;
						case mine:
							for (s = 0; s < G.handCount[player]; s++){
								if ((G.hand[player][s] == 4) || (G.hand[player][s] == 5) || (G.hand[player][s] == 6)){
									choice1 = s;
									break;
								}
							}
							if (G.hand[player][choice1] == 4){
								choice2 = silver;
							}
							else if(G.hand[player][choice1] == 5){
								choice2 = gold;
							}
							else{
								choice2 =gold;
							}
							break;
						case remodel:
							choice1 = (rand() % G.handCount[player]):
							randNum = floor(rand() % 17);
							choice2 = possible[randNum];
							break;
						case baron:
							choice1 = floor(rand() % 2);
							break;
						case minion:
							choice1 = floor(rand() % 2);
							choice2 = floor(rand() % 2);
							break;
						case steward:
							choice1 = floor(rand() % 3);
							choice2 = (rand() % G.handCount[player]);
							choice3 = (rand() % G.handCount[player]);
							//Make sure cards 2 and 3 are different
							while( choice2 == choice3){
								choice3 = (rand() % G.handCount[player]);
							}
							break;
						case ambassador:
							choice1 = (rand() % g.handCount[player]);
							choice2 = floor(rand() % 2);	
							break;
						case embargo:
							choice1 = k[(rand() % 10)];
							break;
						case salvager:
							choice1 = (rand() % G.handCount[player]);
							break;
						default:
							break;
						}
						break;
					}
				}
				//Play Card
				r = playCard(cardPos, choice1, choice2, choice3, &G);
				if ( r == -1) {
					printf("Action failed.\n");
				}
				else{
					printf("Action succeeded.\n");
					printHand(G, player);
					printDiscard(G, player);
				}
				//Try to play the same card again
				if(randNum > 95){
					printf("Player %d is attempts to play ", (player + 1));
					printName(card);
					printf(" again.\n");
					r = playCard(cardPos, choice1, choice2, choice3, &G);
					if (r == -1){
						printf("Action Failed.\n");
					}
					else{
						printf("Action Succesful.\n");
						printHand(G, player);
						printDiscard(G, player);
					}
				}
			}
			else{
				randNum = (rand() % 5);
				card = G.hand[player][randNum];
				cardPos = randNum;
				printf("Player %d attempts to play ", (player + 1));
				printName(card);
				printf(".\n");

				switch (card){
				case feast:
					//Randomly Choose a card except province, gold, or adventurer
					randNum = floor(rand() % 17);
					while ((randNum != 7) && (randNum != 3) && (randNum != 6)){
						randNum = floor(rand() % 17);
					}
					choice1 = possible[randNum];
					break;
				case mine: 
					for (s = 0; s < G.handCount[player]; s++){
						if ((G.hand[player][s] == 4) || (G.hand[player][s] == 5) || (G.hand[player][s] == 6)){
							choice1 = s;
							break;
						}
					}
					if (G.hand[player][choice1] == 4){
						choice2 = silver;
					}
					else if (G.hand[player][choice1] == 5){
						choice2 = gold;
					}
					else{
						choice2 = gold;
					}
					break;
				case remodel:
					choice1 = (rand() % G.handCount[player]);
					randNum = floor(rand() % 17);
					choice2 = possible[randNum];
					break;
				case baron:
					choice1 = floor(rand() % 2);
					break;
				case minion:
					choice1 = floor(rand() % 2);
					choice2 = floor(rand() % 2);
					break;
				case steward: 
					choice1 = floor(rand() % 3);
					choice2 = (rand() % G.handCount[player]);
					choice3 = (rand() % G.handCount[player]);
					//To make sure the two cards are different.
					while (choice2 == choice3){
						choice3 = (rand() % G.handCount[player]);
					}
					break;
				case ambassador:
					choice1 = (rand() % G.handCount[player]);
					choice2 = floor(rand() % 2);
					break;
				case embargo:
					choice1 = k[(rand() % 10)];
					break;
				case salvager:
					choice1 = (rand() % G.handCount[player]);
					break;
				default:
					break;
				}
				
				r = playCard(cardPos, choice1, choice2, choice3, &G);
				if (r == -1){
					printf("Action failed.\n");
				}
				else{
					printf("Action succeded.\n");
					printHand(G, player);
					printDiscard(G, player);
				}
			}
			printf("AFTER ACTION - Player %d's action count = %d.\n", (player + 1), G.numActions);
			printf("AFTER ACTION - Player %d's coins = %d\n", (player + 1), G.coins);
		}

		//Buy Phase of Game
		//(100 - # is prob)
		randNum = (rand() % 100);
		if (randNum < 80){
			printf("BUY PHASE\n");
			printf("BEFORE BUY - Player %d's buy count = %d.\n", (player + 1), G.numBuys);
			printf("BEFORE BUY - Player %d's coins = %d\n", (player + 1), G.coins);

			//Smart Buy Phase
			//Buys from a choice of cards equal to the available coins
			//All the options in the categories have equal odds of being poicked
			if (randNum < 65){
				coins = G.coins;

				if (coins < 2){
					card = copper;
				}
				if( coins == 2){
					randNum = floor(rand() % 3);
					if( randNum == 0){
						card = copper;
					}
					else if( randNum == 1){
						card = estate;
					}
					else {
						card = embargo;
					}
				}
				if ( coins == 3){
					randNum = floor(rand() % 5);
					if(randNum = 0)
					{
						card = silver;
					}
					else if(randNum ==1) {
						card = village;
					}
					else if(randNum == 2){
						card = steward;
					}
					else if(randNum == 3){
						card = ambassador;
					}
					else{
						card = great_hall;
					}
				}
				if (coins == 4){
					randNum = floor(rand() % 10);
					if( randNum == 0){
						card = silver;
					}
					else if( randNum == 1){
						card = feast;
					}
					else if( randNum == 2){
						card = gardens;
					}
					else if( randNum == 3){
						card = remodel;
					}
					else if( randNum == 4){
						card = baron;
					}
					else if( randNum == 5){
						card = cutpurse;
					}
					else if( randNum == 6){
						card = salvager;
					}
					else if( randNum = 7){
						card = sea_hag;
					}
					else if( randNum == 8){
						card = treasure_map;
					}
					else {
						card = smithy;
					}
				}
				if (coins == 5){
					randNum = floor(rand() % 7);
					if (randNum == 0){
						card = silver;
					}
					else if(randNum == 1){
						card = duchy;
					}
					else if (randNum == 2){
						card = council_room;
					}
					else if( randNum == 3){
						card = mine;
					}
					else if( randNum == 4){
						card = minion;
					}
					else if( randNum == 5){
						card = tribute;
					}
					else {
						card = outpost;
					}
				}
				if (( coins == 6) || (coins == 7)){
					randNum = floor(rand() %2);
					if (randNum == 0)
					{
						card = gold;
					}
					else {
						card = adventureer;
					}
				}
				if (coins >= 8){
					card = province;
				}
				r = buyCard(card,&G);
				printBuyCard(G, player, card, r );
			}
			//Randomly Buy a Card
			else{
				randNum = floor(rand() % 17);
				r = buyCard(possible[randNum], &G);
				printBuyCard(G, player, possible[randNum], r);
				if (randNum > 15){
					r = buyCard(possible[randNum], &G);
					printBuyCard(G, player, possible[randNum], r);
				}
			}
			printf("AFTER BUY - Player %d's buy count = %d.\n", (player + 1), G.numBuys);
		}
		printHand(G, player);
		printDeck(G, player);
		printDiscard(G, player);

		//End Phase
		printf("Player %d's turn ends.\n", (player + 1));
		endTurn(&G);
		
		j++;
	}
	//Winner statements
	
	int whoWon[playerCount];

	getWinners(whoWon, &G);

	for (int z = 0; z < playerCount; z++){
		if (whoWon[z] == 1){
			printf("Player %d wins!\n", (z + 1));
		}
	}

	//print score for every player
	for (int z = 0; z < playerCount; z++){
		printf("The Final Score for Player %d = %d.\n", (z + 1), scoreFor(z, &G));
	}

	printf("********Game Over********\n");
	
	return 0;
}

void printName(int cardNumber){
	switch (cardNumber){
	case curse:
		printf("Curse");
		break;
	case estate:
		printf("Estate");
		break;
	case duchy: 
		printf("Duchy");
		break;
	case province:
		printf("Province");
		break;
	case copper:
		printf("Copper");
		break;
	case silver:
		printf("Silver");
		break;
	case gold:
		printf("Gold");
		break;
	case adventurer:
		printf("Adventurer");
		break;
	case council_room: 
		printf("Council Room");
		break;
	case feast:
		printf("Feast");
		break;
	case gardens:
		printf("Gardens");
		break;
	case mine:
		printf("Mine");
		break;
	case remodel:
		printf("Remodel");
		break;
	case smithy:
		printf("Smithy");
		break;
	case village:
		printf("Village");
		break;
	case baron:
		printf("Baron");
		break;
	case great_hall:
		printf("Great Hall");
		break;
	case minion:
		printf("Minion");
		break;
	case steward:
		printf("Steward");
		break;
	case tribute:
		printf("Tribute");
		break;
	case ambassador:
		printf("Ambassador");
		break;
	case cutpurse:
		printf("Cutpurse");
		break;
	case embargo: 
		printf("Embargo");
		break;
	case outpost:
		printf("Outpost");
		break;
	case salvager:
		printf("Salvager");
		break;
	case sea_hag: 
		printf("Sea Hag");
		break;
	case treasure_map:
		print("Treasure Map");
		break;
	default:
		printf("???");
	}

}

void printHand(struct gameState state, int player){
	int i;

	printf("Player %d's cards:\n", (player + 1));

	for (i = 0; i < state.handCount[player]; i++){
		printf("%d - ", (i + 1));
		printName(state.hand[player][i]);
		printf("\n");
	}
}

void printDeck(struct gameState state, int player){
	int i;
	printf("Player %d's deck:\n", (player + 1));
	for (i = 0; i < state.deckCount[player]; i++){
		printf("%d: ", (i + 1));
		printName(state.deck[player][i]);
		printf("\n");
	}
}

void printDiscard(struct gameState state, int player){
	int i;
	printf("Player %d's discard pile:\n", (player + 1));

	for (i = 0; i < state.discardCount[player]; i++){
		printf("%d - ", (i + 1));
		printName(state.discard[player][i]);
		printf("\n");
	}
}

void printBuyCard(struct gameState state, int player, int card, int test){
	printf("Player %d buys ", (player + 1));
	printName(card);
	printf(". Cost = %d.\nPlayer's has %d coins after buying.\n", getCost(card), state.coins);
	if (test != 0){
		printf("Purcahse failed.\n");
		if (supplyCount(card, &state) < 1){
			printf("Supply pile is empty.\n");
		}
		if (state.numBuys < 1){
			printf("Out of buys.\n");
		}
	}
	else{
		printf("Buy succeeded.\n");
	}
}

	
